package com.obas.monitor.codec;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.obas.business.common.vo.AtMessage;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;

public class MessageRequestDecoder extends CumulativeProtocolDecoder {
   // '#' -- flex aut
   // '$' -- html aut
   public static String CONNECT_SIGN_SYMBOL = "connect_sign_symbol";
   
   private Charset ch = Charset.forName("utf-8");
   private CharsetDecoder decoder = ch.newDecoder();
   
   @Override
   protected boolean doDecode(IoSession session, IoBuffer in,
         ProtocolDecoderOutput out) throws Exception {
      if (session.getAttribute(CONNECT_SIGN_SYMBOL) == null) {
         String ss = in.getString(decoder);
         if (ss.equals("#") || ss.equals("$")) {
            session.setAttribute(CONNECT_SIGN_SYMBOL, ss);
            in.position(1);
            out.write(ss);
            return true;
         }
      }
      else {
         int size = in.getInt();
         if (in.remaining() >= size) {
            int id = in.getInt();
            int command = in.getInt();
            Object param = null;
            if (size > 8) {
               param = readObject(SerializationContext.getSerializationContext(), in.asInputStream());
            }
            AtMessage msg = new AtMessage(id, command, param);
            msg.setTime(System.currentTimeMillis());
            out.write(msg);
            return true;
         }
         else {
            in.position(0);
         }
      }
      return false;
   }
   
   private Object readObject(SerializationContext serializationContext, InputStream ins) throws IOException {
      Amf3Input amfin = new Amf3Input(serializationContext);
      amfin.setInputStream(ins);
      Object o = null;
      try {
          o = amfin.readObject();
      } catch (EOFException e) {
          return null;
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
          throw new ClassCastException(e.getMessage());
      } catch (IOException e) {
          e.printStackTrace();
          throw new IOException(e.getMessage());
      }
      return o;
  }
}
